#include "tcplistensocketsslimpl.h"

static int tcplistenssl_eventcb(ioevtcp_t* tcp, short err)
{
    rc_error(tcp != NULL, S_ERROR);
    CTcpListenSocketSslImpl* listen = (CTcpListenSocketSslImpl*)ioevtcp_getctx(tcp);
    listen->Acceptcb(INVALID_SOCKET, NULL, 0, S_ERROR);
    return S_SUCCESS;
}
static int tcplistenssl_acceptcb(ioevtcp_t* tcp, SOCKADDR_PTR sa, socklen_t sl, _sock_t sock)
{
    rc_error(tcp != NULL, S_ERROR);
    CTcpListenSocketSslImpl* listen = (CTcpListenSocketSslImpl*)ioevtcp_getctx(tcp);
    listen->Acceptcb(sock, sa, sl, S_SUCCESS);
    return S_SUCCESS;
}
CTcpListenSocketSslImpl::CTcpListenSocketSslImpl()
{
    m_tcp = (ioevtcp_t*)heap_malloc(sizeof(ioevtcp_t));
}
CTcpListenSocketSslImpl::~CTcpListenSocketSslImpl()
{
    logi("CTcpListenSocketImpl::~CTcpListenSocketImpl");
}
HRESULT CTcpListenSocketSslImpl::BindEvloop(ioevloop_t* loop)
{
    m_evloop = loop;
    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::CloseIo(UINT rw)
{
    m_accept.dispose();
    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::BindIo()
{
    rc_error(m_sock != INVALID_SOCKET, E_FAIL);
    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::OpenIo()
{
    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::BindEvent(IBase* pSocketEvent)
{
    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::UnBindEvent()
{
    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::CreateSock()
{
    HRESULT hr = S_OK;
    m_sock = INVALID_SOCKET;
    m_sock = _createsock(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    rc_error(m_sock != INVALID_SOCKET, E_FAIL);

    set_blocking(m_sock, 1);
    set_keepalive(m_sock, 1);
    set_reuseableport(m_sock, 1);
    set_reuseable(m_sock, 1);
    set_deferaccpet(m_sock, 1);

    ioevtcp_init(m_tcp, m_evloop, m_sock);
    ioevtcp_setctx(m_tcp, this);
    ioevtcp_seteventcb(m_tcp, tcplistenssl_eventcb);
    ioevtcp_setacceptcb(m_tcp, tcplistenssl_acceptcb);

    return hr;
}
HRESULT CTcpListenSocketSslImpl::CloseSock()
{
    HRESULT hr = S_OK;

    rc_error(m_sock != INVALID_SOCKET, E_FAIL);
    ioevtcp_uninit(m_tcp);
    _closesock(m_sock);
    m_sock = INVALID_SOCKET;

    return hr;
}
HRESULT CTcpListenSocketSslImpl::IsOpen()
{
    return S_OK;
}

HRESULT CTcpListenSocketSslImpl::AttachSock(_sock_t sock)
{
    rc_error(sock != INVALID_SOCKET, E_FAIL);
    m_sock = sock;
    return S_OK;
}
_sock_t CTcpListenSocketSslImpl::DetachSock()
{
    _sock_t sock;
    sock = m_sock;
    m_sock = INVALID_SOCKET;
    return sock;
}
_sock_t CTcpListenSocketSslImpl::GetSock()
{
    return m_sock;
}
HRESULT CTcpListenSocketSslImpl::GetReadOperation(IID id, IBase** pBase)
{
    return E_NOTIMPL;
}
HRESULT CTcpListenSocketSslImpl::GetWriteOperation(IID id, IBase** pBase)
{
    return E_NOTIMPL;
}
HRESULT CTcpListenSocketSslImpl::Listen(NET_ADDR addr, NET_PORT port)
{
    rc_error(addr != NULL, E_FAIL);
    rc_error(port != INVALID_NET_PORT, E_FAIL);
    ioevtcp_bind(m_tcp, addr, port);
    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::Listen6(NET_ADDR addr, NET_PORT port)
{
    rc_error(addr != NULL, E_FAIL);
    rc_error(port != INVALID_NET_PORT, E_FAIL);
    ioevtcp_bind6(m_tcp, addr, port);
    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::Accept(int on)
{
    if (on == LISTEN_OPEN) {
        ioevtcp_enable(m_tcp);
    } else if (on == LISTEN_CLOSE) {
        ioevtcp_disable(m_tcp);
    }

    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::BindAccept(IBase* pAccept)
{
    rc_error(pAccept != NULL, E_FAIL);
    return pAccept->QueryInterface(IID_IAcceptListen, (void**)&m_accept);
}
HRESULT CTcpListenSocketSslImpl::UnBindAccpet()
{
    m_accept.dispose();
    return S_OK;
}
HRESULT CTcpListenSocketSslImpl::Acceptcb(_sock_t s, SOCKADDR_PTR sa, socklen_t sl, crtid err)
{
    rc_error(m_accept.m_p != NULL, E_FAIL);

    m_accept->Accept(s, sa, sl, err);

    return S_OK;
}
